/************************************************************************
*Implementacion Comandos de 3 direcciones                               *
*Author     :   Simon Emmanuel Gutierrez Brida                          *
*Version    :   0.1                                                     *
*Fecha      :   Octubre/2011                                            *
*----------------------------------------------------                   *
*************************************************************************/


#include "comando3d.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>




Com3D* nuevoComando(int comando) {
    Com3D *nuevo = (Com3D*) malloc(sizeof(Com3D));
    Param *param1 = (Param*) malloc(sizeof(Param));
    Param *param2 = (Param*) malloc(sizeof(Param));
    Param *param3 = (Param*) malloc(sizeof(Param));
    param1->tipo = CNULL;
    param2->tipo = CNULL;
    param3->tipo = CNULL;
    nuevo->param1 = param1;
    nuevo->param2 = param2;
    nuevo->param3 = param3;
    nuevo->com = comando;
    return nuevo;
}



int obtenerComando(Com3D *comando) {
    return comando->com;    
}

bool esLabel(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->tipo == CLABEL;
    } else if (param == 2) {
        return comando->param2->tipo == CLABEL;
    } else if (param == 3) {
        return comando->param3->tipo == CLABEL;
    }
}

bool esVariable(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->tipo == CVAR;
    } else if (param == 2) {
        return comando->param2->tipo == CVAR;
    } else if (param == 3) {
        return comando->param3->tipo == CVAR;
    }    
}

bool esNull(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->tipo == CNULL;
    } else if (param == 2) {
        return comando->param2->tipo == CNULL;
    } else if (param == 3) {
        return comando->param3->tipo == CNULL;
    }    
}

bool esEntero(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->tipo == CINT;
    } else if (param == 2) {
        return comando->param2->tipo == CINT;
    } else if (param == 3) {
        return comando->param3->tipo == CINT;
    }  
}

bool esReal(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->tipo == CFLOAT;
    } else if (param == 2) {
        return comando->param2->tipo == CFLOAT;
    } else if (param == 3) {
        return comando->param3->tipo == CFLOAT;
    }      
}

bool esBool(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->tipo == CBOOL;
    } else if (param == 2) {
        return comando->param2->tipo == CBOOL;
    } else if (param == 3) {
        return comando->param3->tipo == CBOOL;
    }
}

char* obtenerLabel(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->val->label;
    } else if (param == 2) {
        return comando->param2->val->label;
    } else if (param == 3) {
        return comando->param3->val->label;
    }    
}

Variable* obtenerVariable_com3D(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->val->var;
    } else if (param == 2) {
        return comando->param2->val->var;
    } else if (param == 3) {
        return comando->param3->val->var;
    }
}

int obtenerEntero(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->val->intVal;
    } else if (param == 2) {
        return comando->param2->val->intVal;
    } else if (param == 3) {
        return comando->param3->val->intVal;
    }    
}

float obtenerReal(Com3D *comando, int param) {
    if (param == 1) {
        return comando->param1->val->floatVal;
    } else if (param == 2) {
        return comando->param2->val->floatVal;
    } else if (param == 3) {
        return comando->param3->val->floatVal;
    }    
}

int obtenerBool(Com3D *comando, int param) {
    if (param == 1) {
        if (comando->param1->val->boolVal) {
            return 1;
        } else {
            return 0;   
        }
    } else if (param == 2) {
        if (comando->param2->val->boolVal) {
            return 1;
        } else {
            return 0;   
        }
    } else if (param == 3) {
        if (comando->param3->val->boolVal) {
            return 1;
        } else {
            return 0;   
        }
    }
}


void setearBool(Com3D *comando, int param, bool boolVal) {
    if (param == 1) {
        comando->param1->tipo = CBOOL;
        comando->param1->val = (Valor*) malloc(sizeof(Valor));
        comando->param1->val->boolVal = boolVal;
    } else if (param == 2) {
        comando->param2->tipo = CBOOL;
        comando->param2->val = (Valor*) malloc(sizeof(Valor));
        comando->param2->val->boolVal = boolVal;
    } else if (param == 3) {
        comando->param3->tipo = CBOOL;
        comando->param3->val = (Valor*) malloc(sizeof(Valor));
        comando->param3->val->boolVal = boolVal;
    }
}

void setearReal(Com3D *comando, int param, float floatVal) {
    if (param == 1) {
        comando->param1->tipo = CFLOAT;
        comando->param1->val = (Valor*) malloc(sizeof(Valor));
        comando->param1->val->floatVal = floatVal;
    } else if (param == 2) {
        comando->param2->tipo = CFLOAT;
        comando->param2->val = (Valor*) malloc(sizeof(Valor));
        comando->param2->val->floatVal = floatVal;
    } else if (param == 3) {
        comando->param3->tipo = CFLOAT;
        comando->param3->val = (Valor*) malloc(sizeof(Valor));
        comando->param3->val->floatVal = floatVal;
    }    
}

void setearEntero(Com3D *comando, int param, int intVal) {
    if (param == 1) {
        comando->param1->tipo = CINT;
        comando->param1->val = (Valor*) malloc(sizeof(Valor));
        comando->param1->val->intVal = intVal;
    } else if (param == 2) {
        comando->param2->tipo = CINT;
        comando->param2->val = (Valor*) malloc(sizeof(Valor));
        comando->param2->val->intVal = intVal;
    } else if (param == 3) {
        comando->param3->tipo = CINT;
        comando->param3->val = (Valor*) malloc(sizeof(Valor));
        comando->param3->val->intVal = intVal;
    }
}


void setearLabel(Com3D *comando, int param, char *label) {
    if (param == 1) {
        comando->param1->tipo = CLABEL;
        comando->param1->val = (Valor*) malloc(sizeof(Valor));
        comando->param1->val->label = malloc(strlen(label) + 1);
        strcpy(comando->param1->val->label, label);
    } else if (param == 2) {
        comando->param2->tipo = CLABEL;
        comando->param2->val = (Valor*) malloc(sizeof(Valor));
        comando->param2->val->label = malloc(strlen(label) + 1);
        strcpy(comando->param2->val->label, label);
    } else if (param == 3) {
        comando->param3->tipo = CLABEL;
        comando->param3->val = (Valor*) malloc(sizeof(Valor));
        comando->param3->val->label = malloc(strlen(label) + 1);
        strcpy(comando->param3->val->label, label);
    }    
}

void setearVariable(Com3D *comando, int param, Variable *var) {
    if (param == 1) {
        comando->param1->tipo = CVAR;
        comando->param1->val = (Valor*) malloc(sizeof(Valor));
        comando->param1->val->var = var;
    } else if (param == 2) {
        comando->param2->tipo = CVAR;
        comando->param2->val = (Valor*) malloc(sizeof(Valor));
        comando->param2->val->var = var;
    } else if (param == 3) {
        comando->param3->tipo = CVAR;
        comando->param3->val = (Valor*) malloc(sizeof(Valor));
        comando->param3->val->var = var;
    }    
}

void setearNull(Com3D *comando, int param) {
    if (param == 1) {
        comando->param1->tipo = CNULL;
    } else if (param == 2) {
        comando->param2->tipo = CNULL;
    } else if (param == 3) {
        comando->param3->tipo = CNULL;
    } 
}

void mostrar(Com3D *comando) {
    char * operaciones[20] = {
        "LOAD_CONST",
        "LOAD_MEM",
        "STORE_CONST",
        "STORE_MEM",           
        "COM_MINUS",           
        "COM_ADD",             
        "COM_SUB",             
        "COM_MULT",            
        "COM_DIV",             
        "COM_MOD",             
        "COM_GT",              
        "COM_LT",              
        "COM_EQ",              
        "COM_AND",             
        "COM_OR",              
        "COM_NOT",             
        "COM_MARK",            
        "GOTOLABEL",           
        "GOTOLABEL_COND",
        "COM_RETURN"
    };
    if (obtenerComando(comando) >= 5 && obtenerComando(comando) <= 14) {
        //var var var
        printf("%s %s %s %s\n", operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)), obtenerIdentificador(obtenerVariable_com3D(comando, 2)), obtenerIdentificador(obtenerVariable_com3D(comando, 3)));
    } else if (obtenerComando(comando) == 0) {
        if (esReal(comando, 1)) {
            printf("%s %s %f\n",operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)), comando->param2->val->floatVal);
        } else if (esEntero(comando, 1)) {
            printf("%s %s %d\n",operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)), comando->param2->val->intVal);
        }
    } else if (obtenerComando(comando) == 1 || obtenerComando(comando) == 3) {
        printf("%s %s %s\n",operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)), obtenerIdentificador(obtenerVariable_com3D(comando, 2)));
    } else if (obtenerComando(comando) == 2) {
        if (esReal(comando, 1)) {
            printf("%s %f %s\n",operaciones[obtenerComando(comando)], comando->param1->val->floatVal, obtenerIdentificador(obtenerVariable_com3D(comando, 2)));
        } else if (esEntero(comando, 1)) {
            printf("%s %d %s\n",operaciones[obtenerComando(comando)], comando->param1->val->intVal, obtenerIdentificador(obtenerVariable_com3D(comando, 2)));
        }  
    } else if (obtenerComando(comando) == 4 || obtenerComando(comando) == 15) {
        //var var null
        printf("%s %s %s\n", operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)), obtenerIdentificador(obtenerVariable_com3D(comando, 2)));
    } else if (obtenerComando(comando) == 16 || obtenerComando(comando) == 17) {
        //label null null
        printf("%s %s\n", operaciones[obtenerComando(comando)], comando->param1->val->label);
    } else if (obtenerComando(comando) == 18) {
        //var label
        printf("%s %s %s\n", operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)), comando->param2->val->label);
    } else if (obtenerComando(comando) == 19) {
        printf("%s %s\n", operaciones[obtenerComando(comando)], obtenerIdentificador(obtenerVariable_com3D(comando, 1)));
    }
    
}


